package leo.gptBot.webSocket;

import com.alibaba.fastjson2.JSONObject;
import leo.gptBot.constant.GocqActionEnum;
import leo.gptBot.constant.MessageTypeEnum;
import leo.gptBot.constant.MetaEventEnum;
import leo.gptBot.constant.PostTypeEnum;
import leo.gptBot.dto.response.Params;
import leo.gptBot.dto.request.Message;
//import leo.gptBot.utils.WsSyncRequestUtil;
import leo.gptBot.dto.response.RequestBox;
import leo.gptBot.thread.ProcessMessageTask;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.util.CollectionUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ：Leo
 * @date ：Created in 2024/7/22 14:17
 * @description：
 */
@Slf4j
public class WebSocketServer extends TextWebSocketHandler {
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    private static class UserSession {
        private Long botId;
        private WebSocketSession session;
    }

    private static final Map<String,UserSession> sessionCache = new ConcurrentHashMap<>();

    public static int getConnections(){
        return sessionCache.size();
    }

    @Override
    public void afterConnectionEstablished(final WebSocketSession session) throws Exception {
        sessionCache.put(session.getId(),new UserSession(null,session));
        log.info("客户端连接成功,sessionId:{}，客户端数量：{}", session.getId(),getConnections());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        final String s = message.getPayload();
        log.debug("[ws server]收到消息 {}",s);
        try {
            JSONObject jsonObject = JSONObject.parseObject(s);
            Object obj = jsonObject.get("message");
            if(obj instanceof String){
                return;
            }
            final Message bean = JSONObject.parseObject(s, Message.class);
            if(PostTypeEnum.meta_event.toString().equals(bean.getPostType()) && MetaEventEnum.heartbeat.toString().equals(bean.getMetaEventType())){
                // 心跳包
                return;
            }
            ProcessMessageTask.execute(session,bean);
        }catch (Exception e){
            log.error("解析payload异常:{}",s,e);
        }
    }
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("连接异常,sessionId:{}",session.getId(),exception);
        removeClient(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        log.info("连接断开,sessionId:{},{}",session.getId(),closeStatus.toString());
        removeClient(session);
    }
    private void removeClient(WebSocketSession session){
        String id = session.getId();
        UserSession userSession = sessionCache.get(id);
        if(userSession != null){
            sessionCache.remove(id);
            log.info("客户端断开：{}  当前连接数：{}",userSession.getBotId(),getConnections());
        }
    }
    public static void sendMessage(WebSocketSession session, String text){
        try {
            log.debug("发送消息给gocq {}",text);
            session.sendMessage(new TextMessage(text));
        } catch (Exception e) {
            log.error("发送消息发生异常,session:{},消息：{}",session,text,e);
        }
    }

    /**
     * 发送私聊消息
     * @param session 客户端session
     * @param userId 对方qq
     * @param message 消息
     * @param autoEscape 是否以纯文本发送 true:以纯文本发送，不解析cq码
     */
    public static void sendPrivateMessage(WebSocketSession session, Long userId, String message, boolean autoEscape){
        RequestBox<Params> paramsRequestBox = new RequestBox<>();
        paramsRequestBox.setAction(GocqActionEnum.SEND_PRIVATE_MSG.getAction());

        Params params = new Params();
        params.setMessageType(MessageTypeEnum.privat.getType());
        params.setAutoEscape(autoEscape);
        params.setUserId(userId);
        params.setMessage(message);

        paramsRequestBox.setParams(params);

        sendMessage(session,JSONObject.toJSONString(paramsRequestBox));
    }
}
